package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.constants.WmNewsMessageConstants;
import com.heima.model.common.WemediaConstants;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.thread.WmThreadLocalUtil;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.service.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * impl wm新闻服务
 *
 * @author DiXiaoNie
 * @date 2022/12/21
 * @since 2022/12/21 21:12
 */
@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Autowired
    private WmNewsMaterialService wmNewsMaterialService;

    @Autowired
    private WmMaterialService wmMaterialService;

    @Autowired
    private WmNewsAutoScanService wmNewsAutoScanService;

    @Autowired
    private WmNewsTaskService wmNewsTaskService;

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;


    /**
     * 查询所有
     *
     * @param dto dto
     * @return {@link ResponseResult }
     * @author DiXiaoNie
     * @date 2022/12/21
     */
    @Override

    public ResponseResult findAll(WmNewsPageReqDto dto) {
        //1.检查参数
        if (dto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //分页参数检查
        dto.checkParam();

        //获取当前登录人的信息
        WmUser user = WmThreadLocalUtil.getWmUserThreadLocal();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //2.分页条件查询
        IPage<WmNews> page = new Page<>(dto.getPage(), dto.getSize());
        LambdaQueryWrapper<WmNews> queryWrapper = Wrappers.<WmNews>lambdaQuery()
                //状态精确查询
                .eq(dto.getStatus() != null, WmNews::getStatus, dto.getStatus())
                //频道精确查询
                .eq(dto.getChannelId() != null, WmNews::getChannelId, dto.getChannelId())
                //时间范围查询
                .between(dto.getBeginPubdate() != null && dto.getEndPubdate() != null, WmNews::getPublishTime, dto.getBeginPubdate(), dto.getEndPubdate())
                //关键字模糊查询
                .like(StringUtils.isNotBlank(dto.getKeyword()), WmNews::getTitle, dto.getKeyword())
                //查询当前登录用户的文章
                .eq(WmNews::getUserId, user.getId())
                //发布时间倒序查询
                .orderByDesc(WmNews::getCreatedTime);

        //3.结果返回
        page = page(page, queryWrapper);
        ResponseResult responseResult = new PageResponseResult(dto.getPage(), dto.getSize(), (int) page.getTotal());
        responseResult.setData(page.getRecords());
        return responseResult;
    }

    /**
     * 上架或下架
     *
     * @param wmNews wm新闻
     * @return {@link ResponseResult }
     * @author DiXiaoNie
     * @date 2022/12/23
     */
    @Override
    public ResponseResult downOrUp(WmNews wmNews) {
        //参数校验
        if (wmNews.getId() == null || wmNews.getEnable() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //根据文章id查询文章是否存在
        WmNews wmNewss = this.getById(wmNews.getId());
        //文章不存在或状态不为已发布直接返回
        if (wmNewss == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR.getCode(), "文章不存在");
        }
        if (wmNewss.getStatus() != WmNews.Status.PUBLISHED.getCode()) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID.getCode(), "该文章不可上架或下架");
        }
        //更新文章状态
        this.updateById(wmNews);
        //发送消息给kafka
        Map map = new HashMap();
        map.put("articleId", wmNewss.getArticleId());
        map.put("enable", wmNewss.getEnable());
        kafkaTemplate.send(WmNewsMessageConstants.WM_NEWS_UP_OR_DOWN_TOPIC, JSON.toJSONString(map));
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);

    }

    /**
     * 删除文章
     *
     * @param id id
     * @return {@link ResponseResult }
     * @author DiXiaoNie
     * @date 2022/12/22
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult deleteNews(Integer id) {
        if (id == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        WmNews wmNews = this.getById(id);
        if (wmNews.getStatus() == 9 && wmNews.getEnable() == 1) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID.getCode(), "文章已上架不可删除");
        }

        this.wmNewsMaterialService.remove(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getNewsId, id));

        this.removeById(id);


        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 回显文章
     *
     * @param id id
     * @return {@link ResponseResult }
     * @author DiXiaoNie
     * @date 2022/12/21
     */
    @Override
    public ResponseResult findNews(Integer id) {
        if (id == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        WmNews wmNews = this.getOne(Wrappers.<WmNews>lambdaQuery().eq(WmNews::getId, id));
        if (wmNews == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        return ResponseResult.okResult(wmNews);

    }

    /**
     * 提交
     *
     * @param dto dto
     * @return {@link ResponseResult }
     * @author DiXiaoNie
     * @date 2022/12/21
     */
    @Override
    public ResponseResult submit(WmNewsDto dto) {
        //1.参数校验
        if (dto == null || StringUtils.isBlank(dto.getContent())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        if (dto.getType() == -1) {
            dto.setTitle(null);

        }

        //2.保存或者修改文章
        WmNews wmNews = new WmNews();
        BeanUtils.copyProperties(dto, wmNews);

        //封面图片
        List<String> images = dto.getImages();
        wmNews.setImages(StringUtils.join(images, ","));
        wmNews.setCreatedTime(new Date());
        wmNews.setUserId(WmThreadLocalUtil.getWmUserThreadLocal().getId());
        Boolean aBoolean = saveOrUpdateWmNews(wmNews);
        if (!aBoolean) {
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }
        //3.判断是否是草稿
        if (dto.getStatus() == 0) {
            return ResponseResult.okResult("此操作是保存草稿操作");
        }
        //3.1 从文章中抽取图片
        List<String> extractImageUrlList = extractContentImage(wmNews);

        //4.关联文章中的图片与文章关系
        saveNewsMaterial(wmNews, extractImageUrlList, (short) 0);

        //5.关联封面图片与文章的关系
        coverImageToNews(dto, wmNews, extractImageUrlList);

        //this.wmNewsAutoScanService.autoScanWmNews(wmNews.getId());
        //审核文章
        this.wmNewsTaskService.addNewsToTask(wmNews.getId(), wmNews.getPublishTime());

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 封面图片新闻
     *
     * @param dto                 dto
     * @param wmNews              wm新闻
     * @param extractImageUrlList 提取图像url列表
     * @author DiXiaoNie
     * @date 2022/12/21
     */
    private void coverImageToNews(WmNewsDto dto, WmNews wmNews, List<String> extractImageUrlList) {
        List<String> coverImage = dto.getImages();
        if (dto.getType() == null) {
            //1.如果内容图片个数大于等于1小于3的话
            if (extractImageUrlList.size() >= 1 && extractImageUrlList.size() < 3) {
                coverImage = extractImageUrlList.stream().limit(1).collect(Collectors.toList());
                wmNews.setType((short) 1);
            } else if (extractImageUrlList.size() >= 3) {
                coverImage = extractImageUrlList.stream().limit(3).collect(Collectors.toList());
                wmNews.setType((short) 3);
            } else {
                //封面中没有图片
                wmNews.setType((short) 0);
            }
            wmNews.setImages(StringUtils.join(coverImage, ","));
            this.updateById(wmNews);
        }
        saveNewsMaterial(wmNews, coverImage, (short) 1);
    }

    /**
     * 保存新闻材料
     *
     * @param wmNews              wm新闻
     * @param extractImageUrlList 提取图像url列表
     * @author DiXiaoNie
     * @date 2022/12/21
     */
    private void saveNewsMaterial(WmNews wmNews, List<String> extractImageUrlList, Short type) {
        if (extractImageUrlList != null && extractImageUrlList.size() > 0) {
            //根据图片url集合 获取对应的素材对象集合
            List<WmMaterial> wmMaterials = wmMaterialService.list(Wrappers.<WmMaterial>lambdaQuery().in(WmMaterial::getUrl, extractImageUrlList));
            //根据stream流去解析素材id
            List<Integer> collectImageIds = wmMaterials.stream().map(WmMaterial::getId).collect(Collectors.toList());
            //批量新增
            this.wmNewsMaterialService.saveRelations(collectImageIds, wmNews.getId(), type);
        }
    }

    /**
     * 提取图像内容
     *
     * @author DiXiaoNie
     * @date 2022/12/21
     */
    private List<String> extractContentImage(WmNews wmNews) {

        /*转换类型*/                /*获取文章内容*/
        return JSONArray.parseArray(wmNews.getContent(), Map.class).stream()
                .filter(map -> map.get("type").equals(WemediaConstants.WM_NEWS_TYPE_IMAGE))
                .map(map -> (String) map.get("value"))
                .collect(Collectors.toList());
    }

    /**
     * 保存或更新文章
     *
     * @param wmNews wm新闻
     * @author DiXiaoNie
     * @date 2022/12/21
     */
    private Boolean saveOrUpdateWmNews(WmNews wmNews) {
        //判断是否是修改
        //为空是新增
        if (wmNews.getId() == null) {
            boolean status = this.save(wmNews);
            return status ? Boolean.TRUE : Boolean.FALSE;
            //反之为修改
        } else {
            //1.删除素材中间表
            LambdaQueryWrapper<WmNewsMaterial> queryWrapper = Wrappers.<WmNewsMaterial>lambdaQuery()
                    .eq(WmNewsMaterial::getNewsId, wmNews.getId());
            this.wmNewsMaterialService.remove(queryWrapper);
            //2.修改wm_news表
            boolean status = this.updateById(wmNews);
            return status ? Boolean.TRUE : Boolean.FALSE;
        }
    }

}
